home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
fish
/
726-750
/
727
/
format
/
source
/
format.c
next >
Wrap
C/C++ Source or Header
|
1995-03-18
|
28KB
|
1,112 lines
/**************************************************************************/
/* Format */
/* Version 1.00 */
/* */
/* This is a replacement for the AmigaDOS "Format" command. It sports */
/* (for the Workbench user) more friendly user-interface, although it is */
/* virtually identical to the standard Format command where the CLI */
/* interface is concerned. */
/* */
/* This program is Copyright 1992 by Dave Schreiber, All Rights Reserved. */
/* This program may not be sold for more than a small copying and shipping*/
/* and handling fee, except by written permission of Dave Schreiber. */
/* */
/* Version list: */
/* 1.00 - First release (August 31, 1992) */
/**************************************************************************/
/*System header files*/
#include <exec/types.h>
#include <exec/exec.h>
#include <intuition/intuition.h>
#include <dos/dos.h>
#include <dos/filehandler.h>
#include <workbench/startup.h>
#include <libraries/gadtools.h>
#include <workbench/icon.h>
#include <devices/trackdisk.h>
#include <dos/rdargs.h>
/*Prototypes for system functions*/
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/dos.h>
#include <proto/gadtools.h>
#include <proto/icon.h>
#include <proto/graphics.h>
/*Other headers*/
#include "Format.h"
#include "GUI.h"
/*These hold the user's selections*/
/*They are initialized in main()*/
BOOL FFS;
BOOL QuickFmt;
BOOL Verify;
BOOL Icon;
/*This holds the pointer to the Workbench startup message, if we're started*/
/*from Workbench*/
extern struct WBStartup *WBenchMsg;
/*Library base pointers*/
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *GadToolsBase,*IconBase;
/*This is initialized in GUI.c and holds the location and size*/
/*of the progress indicator box in the status window*/
extern Rect box;
BPTR StdErr=NULL;
/*For use with the CLI "Version" command*/
char *Version = "$VER: NewFormat V1.00 (31.8.92)";
/*The entry point for the program (_main to keep a CLI window from opening*/
/*when the program is run from Workbench)*/
_main()
{
UWORD disk;
char volumeName[256];
prepResult stat;
char statusString[80];
/*Open the various shared libraries that are needed*/
IntuitionBase=(struct Library *)OpenLibrary("intuition.library",37L);
GfxBase=(struct Library *)OpenLibrary("graphics.library",37L);
IconBase=(struct Library *)OpenLibrary("icon.library",37L);
GadToolsBase=(struct Library *)OpenLibrary("gadtools.library",37L);
/*Check to see that they all opened, and exit if any did not*/
if(IntuitionBase==NULL || GfxBase==NULL || IconBase==NULL ||
GadToolsBase==NULL)
cleanup(100);
if(WBenchMsg!=NULL)
{
/*If we're running from Workbench, and the user did not select*/
/*a drive, print an error and exit*/
if(WBenchMsg->sm_NumArgs==1)
{
printError("Please select a drive to format and try again.",NULL,NULL);
cleanup(100);
}
/*Get the visual info, etc.*/
SetupScreen();
/*For every selected disk...*/
for(disk=1;disk<WBenchMsg->sm_NumArgs && stat!=eQuit;disk++)
{
/*This will hold the disk's new name*/
char newName[36];
/*Initialize the format settings*/
FFS=FALSE;
QuickFmt=FALSE;
Verify=TRUE;
Icon=TRUE;
/*Get the volume/device name of the disk to format*/
getVolumeName(volumeName,WBenchMsg->sm_ArgList,disk);
/*If there is no lock to the volume, that means it is */
/*unformatted, so just use the name given to us by Workbench*/
if(WBenchMsg->sm_ArgList[disk].wa_Lock==NULL)
strcpy(volumeName,WBenchMsg->sm_ArgList[disk].wa_Name);
/*Open the options window*/
if((stat=OpenPrepWindow(volumeName))==0)
{
/*Get the user's input*/
stat=getPrepInput();
/*And close the window*/
ClosePrepWindow();
/*If the user selected 'OK'*/
if(stat==eOK)
{
/*Get the new name of the disk*/
strcpy(newName,((struct StringInfo *)
(PrepGadgets[GD_NameGadget]->SpecialInfo))->Buffer);
/*Ask the user for verification*/
if(askAreYouSure(volumeName,
(WBenchMsg->sm_ArgList[disk].wa_Lock!=NULL)))
{
/*If everything's OK, open the status window*/
if((stat=OpenStatusWindow(statusString))==0)
{
/*And format the disk*/
formatVolume(&(WBenchMsg->sm_ArgList[disk].wa_Lock),
volumeName,newName,FFS,QuickFmt,Verify,Icon,
statusString);
/*We're done, so close the status window*/
CloseStatusWindow();
}
}
}
}
}
/*Free the visual info, etc.*/
CloseDownScreen();
}
else /*We've been run from the CLI*/
{
char driveName[64];
BPTR driveLock;
struct Process *process;
APTR oldWdw;
char temp[32];
char temp2[4];
DriveLayout junk;
/*Open a 'stderr' I/O channel to the shell*/
/*(the normal stderr was not opened since we used _main() ) */
StdErr=Open("CONSOLE:",MODE_OLDFILE);
/*Make sure requestors don't open*/
process=(struct Process *)FindTask(0L);
oldWdw=process->pr_WindowPtr;
process->pr_WindowPtr=(APTR)(-1);
/*Get the command-line arguments*/
parseArgs(driveName,volumeName,&FFS,&Icon,&QuickFmt,&Verify);
/*Get a lock on the selected drive*/
/*(note: NULL is a valid return value; it means that the disk we*/
/*want to format is itself unformatted)*/
driveLock=Lock(driveName,ACCESS_READ);
strcpy(temp,driveName);
/*Get the volume/drive name*/
if(volumeToDevName(driveLock,temp,&junk))
{
/*Wait for the user to tell us to go ahead*/
Write(Output(),"Insert the disk to be formatted in drive ",41);
Write(Output(),temp,strlen(temp));
Write(Output()," and press RETURN ",18);
Read(Input(),temp2,1);
/*Format the disk*/
formatVolume(&driveLock,temp,volumeName,FFS,QuickFmt,Verify,Icon,
statusString);
}
else
Write(Output(),"Cannot find the specified drive!\n",33);
Close(StdErr);
/*Restore the old contents of this pointer*/
process->pr_WindowPtr=(APTR)(-1);
Write(Output(),"\n",1);
}
cleanup(0);
return(0);
}
/*This functions handles the low-level format, the high-level format, the*/
/*creation of icons, etc.*/
void formatVolume(BPTR *volumeLock,char *volumeName,char *newName,BOOL ffs,
BOOL quick,BOOL verify,BOOL icon,char *statString)
{
struct IOExtTD *io1;
BOOL fmtResult=TRUE;
int result;
char deviceName[64];
DriveLayout layout;
struct MsgPort *devPort;
BOOL writeProtCont=TRUE;
/*If the volume lock is NULL, assume that the volumeName string holds*/
/*a valid device pointer*/
if(*volumeLock==NULL)
strcpy(deviceName,volumeName);
/*Get the drive name (if possible)*/
if(!volumeToDevName(*volumeLock,deviceName,&layout))
{
printError("Can't find the drive!",NULL,NULL);
return;
}
/*This port will be used to communicate with the filesystem*/
devPort=DeviceProc(deviceName);
if(devPort==NULL)
{
printError("Can't find the drive",NULL,NULL);
return;
}
/*Inhibit the drive*/
DoPkt(devPort,ACTION_INHIBIT,DOSTRUE,NULL,NULL,NULL);
/*If we got a lock to the volume that we're going to format it, destroy*/
/*it, since the volume that it points to is about to be erased anyway*/
if(*volumeLock!=NULL)
{
UnLock(*volumeLock);
*volumeLock=NULL;
}
/*Open the disk device*/
if((io1=OpenDrive(layout.devName,layout.unit,layout.flags))!=NULL)
{
/*Determine the write protect status*/
io1->iotd_Req.io_Data=NULL;
io1->iotd_Req.io_Length=0;
io1->iotd_Req.io_Command=TD_PROTSTATUS;
DoIO((struct IOReq *)io1);
/*Loop while the disk stays protected and user keeps pressing Retry*/
while(io1->iotd_Req.io_Actual!=0 &&
(writeProtCont=alertIsWriteProtected(volumeName)))
DoIO((struct IOReq *)io1);
/*If the disk is not write-protected*/
if(writeProtCont)
{
/*Do a full format if the user didn't select the 'Quick' option*/
if(!quick)
fmtResult=doFullFormat(&layout,statString,volumeName,io1);
/*If the format was successful*/
if(fmtResult)
{
/*Write an extra carriage return, if run from the CLI*/
if(WBenchMsg==NULL)
Write(Output(),"\n",1);
/*Tell the user that we're doing the high-level format*/
fmtResult=!updateStatWindow("Formatting disk...",1000);
/*If the user hasn't clicked on 'Stop', do the high-level format*/
if(fmtResult)
result=Format(deviceName,newName,
ffs ? ID_FFS_DISK : ID_DOS_DISK);
}
}
else
printError("Cannot format volume",volumeName,
"because the disk is write protected");
/*Close the disk device*/
CloseDrive(io1);
}
else
{
printError("Couldn't access the device",NULL,NULL);
return;
}
/*Uninhibit the drive*/
DoPkt(devPort,ACTION_INHIBIT,DOSFALSE,NULL,NULL,NULL);
/*Wait for the drive to come on line*/
Delay(50);
/*If the disk was never unprotected, return*/
if(!writeProtCont)
return;
/*If the format was successful and the user wants icons created*/
if(icon && result==DOSTRUE)
{
struct DiskObject *trashIcon;
BPTR trashLock;
/*Update the user*/
fmtResult=!updateStatWindow("Creating Trashcan ",1000);
/*If she didn't press 'Stop'*/
if(fmtResult)
{
/*Create the trashcan name (<volume>:Trashcan)*/
strcpy(deviceName,newName);
strcat(deviceName,":");
strcat(deviceName,"Trashcan");
/*Create the trashcan directory*/
trashLock=CreateDir(deviceName);
/*If it was successfully created*/
if(trashLock!=NULL)
{
UnLock(trashLock);
/*Get the trashcan icon*/
trashIcon=GetDefDiskObject(WBGARBAGE);
/*If there wasn't an error*/
if(trashIcon!=NULL)
{
/*Write the icon to disk*/
if(!PutDiskObject(deviceName,trashIcon))
printError("There was an error while creating the trashcan",
NULL,NULL);
/*and free it*/
FreeDiskObject(trashIcon);
}
else
printError("There was an error while creating the trashcan",
NULL,NULL);
}
else
printError("There was an error while creating the trashcan directory",
NULL,NULL);
}
}
return;
}
/*This function does a full (low-level) format of a disk*/
BOOL doFullFormat(DriveLayout *layout,char *statString,char *devName,
struct IOExtTD *io1)
{
ULONG *write;
ULONG trackSize,sectorPos,numTracks;
LONG track;
int c;
UBYTE error=2;
BOOL errorB=FALSE;
/*Get the size of a track (#surfaces*#blocks*#longwordsPerTrack*4*/
trackSize=layout->surfaces*layout->blockSize*4*layout->BPT;
/*Allocate enough memory for one track*/
write=AllocMem(trackSize,layout->memType|MEMF_CLEAR);
if(write!=NULL)
{
/*Initialize the IORequest*/
io1->iotd_Req.io_Data=write;
io1->iotd_Req.io_Length=trackSize;
/*Get the starting byte position in the volume*/
sectorPos=layout->lowCyl*trackSize;
/*Get the number of tracks to format*/
numTracks=layout->highCyl-layout->lowCyl+1;
/*Clear the status window*/
error=(updateStatWindow(" ",0)) ? 0 : error;
/*For each track*/
for(track=0;track<numTracks && error!=0;track++)
{
/*Setup to format the disk*/
io1->iotd_Req.io_Command=TD_FORMAT;
io1->iotd_Req.io_Offset=sectorPos;
/*Update the status window*/
strcpy(statString,"Formatting cylinder ");
stci_d(&statString[20],track+layout->lowCyl);
strcat(statString,", ");
stci_d(&statString[strlen(statString)],numTracks-track-1);
strcat(statString," to go ");
error=(updateStatWindow(statString,track*1000/numTracks)) ?0:error;
/*If the user didn't press 'Stop'*/
if(error!=0)
{
error=(DoIO((struct IOReq *)io1)) ? 0 : error;
if(error==0)
printError("A formatting error occured",NULL,NULL);
}
/*If we're suppossed to verify, and the user didn't press 'Stop'*/
if(Verify && error!=0)
{
/*Setup the same IORequest to do a read*/
io1->iotd_Req.io_Command=CMD_READ;
/*Update the status*/
strcpy(statString," Verifying cylinder ");
stci_d(&statString[20],track+layout->lowCyl);
strcat(statString,", ");
stci_d(&statString[strlen(statString)],numTracks-track-1);
strcat(statString," to go ");
error=(updateStatWindow(statString,
( (1+(track*2))*1000)/(2*numTracks) )) ? 0 : error;
/*If the user hasn't pressed 'Stop'*/
if(error!=0)
{
/*Do the read*/
if(DoIO((struct IOReq *)io1))
{
if(--error==0)
printError("A verify error occurred",NULL,NULL);
errorB=TRUE;
}
}
/*Check the data that was read back.*/
for(c=0;c<trackSize>>2 && error!=0;c++)
{
/*If there was an error*/
if(write[c]!=0L)
{
/*Record the fact*/
if(!errorB)
{
errorB=TRUE;
if(--error==0)
/*Print an error message*/
printError("A verify error occurred",NULL,NULL);
}
write[c]=0L;
}
}
if(!errorB && error!=2)
error=2;
}
/*Get the byte position of the next track*/
if(errorB)
{
errorB=FALSE;
track--;
}
else
sectorPos+=trackSize;
}
/*We're done, so free the track memory*/
FreeMem(write,trackSize);
}
else
printError("Couldn't allocate write buffer",NULL,NULL);
return(error!=0);
}
/*Used in askAreYouSure()*/
struct EasyStruct areYouSure=
{
sizeof(struct EasyStruct),
0,
"Format Request...",
"Are you sure you want to format volume\n%s\n(the contents of the disk will be destroyed)?",
"Yes|No"
};
/*Ask the user if she really wants to format the disk*/
BOOL askAreYouSure(char *volumeName,BOOL truncColon)
{
char name[36];
APTR args[2];
UBYTE result;
/*Get the device name*/
strcpy(name,volumeName);
/*Truncate the trailing colon if so specified*/
if(truncColon)
name[strlen(name)-1]=NULL;
/*Setup the device name as the argument to the requestor*/
args[0]=name;
args[1]=NULL;
/*Put up the requestor*/
result=EasyRequestArgs(NULL,&areYouSure,NULL,args);
/*Return the result*/
return(result==1);
}
/*Used in askAreYouSure()*/
struct EasyStruct writeProtected=
{
sizeof(struct EasyStruct),
0,
"Format Request...",
"Volume\n%s\nis write protected",
"Retry|Cancel"
};
/*Alert the user to the fact that the disk is write protected, and give*/
/*the user a chance to unprotect the disk*/
BOOL alertIsWriteProtected(char *devName)
{
APTR args[2];
BYTE result;
/*Setup the device name as the argument to the requestor*/
args[0]=devName;
args[1]=NULL;
/*Put up the requestor*/
result=EasyRequestArgs(NULL,&writeProtected,NULL,args);
/*Return the result*/
return(result==1);
}
/*This is used to print errors*/
struct EasyStruct errorReq=
{
sizeof(struct EasyStruct),
0,
"Format Request...",
NULL,
"Ok"
};
char *oneLine="%s";
char *twoLine="%s\n%s";
char *threeLine="%s\n%s\n%s";
/*Print one, two, or three lines of error messages in an EasyRequestor*/
/*or to 'StdErr'*/
void printError(char *first,char *second,char *third)
{
APTR args[4];
args[0]=args[3]=NULL;
/*If we're running from the CLI*/
if(WBenchMsg==NULL)
{
/*And a StdErr handle was opened successfully*/
if(StdErr!=NULL)
{
char LF=0x0A;
/*Print the first line*/
if(first!=NULL)
{
Write(StdErr,first,strlen(first));
Write(StdErr," ",1);
}
/*Print the second line*/
if(second!=NULL)
{
Write(StdErr,second,strlen(second));
Write(StdErr," ",1);
}
/*Print the third line*/
if(third!=NULL)
{
Write(StdErr,third,strlen(third));
Write(StdErr," ",1);
}
/*Print the terminating carriage return*/
Write(StdErr,&LF,1);
}
}
else /*Otherwise, we're running from Workbench, so put up the requestor*/
{
/*Three lines*/
if(third!=NULL)
{
args[2]=third;
args[1]=second;
args[0]=first;
errorReq.es_TextFormat=threeLine;
}
else if(second!=NULL) /*Two lines*/
{
args[1]=second;
args[0]=first;
errorReq.es_TextFormat=twoLine;
}
else if(first!=NULL) /*One line*/
{
args[0]=first;
errorReq.es_TextFormat=oneLine;
}
/*Put up the requestor*/
EasyRequestArgs(NULL,&errorReq,NULL,args);
}
return;
}
/*Get the name of a volume, given a lock to that volume*/
void getVolumeName(char *name,struct WBArg *argList,UWORD disk)
{
/*Get the name*/
if(NameFromLock(argList[disk].wa_Lock,name,256)==DOSFALSE)
/*Or return <unknown> if the name couldn't be determined*/
strcpy(name,"<unknown>");
return;
}
/*Exit from the program, closing any open libraries*/
void cleanup(ULONG err)
{
if(IntuitionBase!=NULL)
CloseLibrary((struct Library *)IntuitionBase);
if(GfxBase!=NULL)
CloseLibrary((struct Library *)GfxBase);
if(GadToolsBase!=NULL)
CloseLibrary(GadToolsBase);
if(IconBase!=NULL)
CloseLibrary(IconBase);
exit(err);
}
/*Get input from the original window*/
prepResult getPrepInput(void)
{
struct IntuiMessage *mesg;
ULONG class;
ULONG code;
struct Gadget *gadget;
struct TagItem tags[2];
/*Setup tags that will be used to toggle the states of checkbox gadgets*/
tags[0].ti_Tag=GTCB_Checked;
tags[1].ti_Tag=TAG_DONE;
tags[1].ti_Data=NULL;
/*Loop until the user presses 'OK' or 'Cancel'*/
for(;;)
{
/*Wait for input*/
Wait(1<<PrepWnd->UserPort->mp_SigBit);
/*Get the input*/
mesg=GT_GetIMsg(PrepWnd->UserPort);
/*Loop while there are messages to be processed*/
while(mesg!=NULL)
{
/*Get the message type, etc.*/
class=mesg->Class;
code=mesg->Code;
gadget=(struct Gadget *)mesg->IAddress;
/*Reply to the message*/
GT_ReplyIMsg(mesg);
/*Act on the message*/
switch(class)
{
/*User clicked on close gadget. Treat it as a click on 'Cancel'*/
case CLOSEWINDOW:
return(eQuit);
/*User pressed a gadget*/
case GADGETUP:
switch(gadget->GadgetID)
{
/*Checkbox gadgets*/
/*(each toggles the appropriate status flag)*/
case GD_FFSGadget:
FFS=!FFS;
break;
case GD_IconGadget:
Icon=!Icon;
break;
case GD_QuickFmtGadget:
QuickFmt=!QuickFmt;
break;
case GD_VerifyGadget:
Verify=!Verify;
break;
/*OK*/
case GD_OKGadget:
return(eOK);
/*Cancel*/
case GD_CancelGadget:
return(eCancel);
}
break;
/*Keypress (gadget equivalents)*/
case VANILLAKEY:
switch(code)
{
/*Disk name*/
case 'n':
case 'N':
ActivateGadget(PrepGadgets[GD_NameGadget],
PrepWnd,NULL);
break;
/*FFS*/
case 'f':
case 'F':
tags[0].ti_Data=(FFS=!FFS);
/*Toggle the checkmark state of the gadget*/
GT_SetGadgetAttrsA(PrepGadgets[GD_FFSGadget],
PrepWnd,NULL, tags);
break;
/*Verify*/
case 'v':
case 'V':
tags[0].ti_Data=(Verify=!Verify);
GT_SetGadgetAttrsA(PrepGadgets[GD_VerifyGadget],
PrepWnd,NULL, tags);
break;
/*Quick Format*/
case 'q':
case 'Q':
tags[0].ti_Data=(QuickFmt=!QuickFmt);
GT_SetGadgetAttrsA(PrepGadgets[GD_QuickFmtGadget],
PrepWnd,NULL, tags);
break;
/*Create icons*/
case 'r':
case 'R':
tags[0].ti_Data=(Icon=!Icon);
GT_SetGadgetAttrsA(PrepGadgets[GD_IconGadget],
PrepWnd,NULL, tags);
break;
/*Cancel*/
case 'c':
case 'C':
return(eCancel);
/*OK*/
case 'o':
case 'O':
return(eOK);
}
break;
}
/*Get the next message*/
mesg=GT_GetIMsg(PrepWnd->UserPort);
}
}
return(FALSE);
}
/*Convert a volume name to a device name, and get information*/
/*on the layout of the disk*/
BOOL volumeToDevName(BPTR volumeLock,char *dev,DriveLayout *layout)
{
BOOL stat;
struct DosList *dosList;
struct DeviceNode *devNode;
char name[36];
char *temp;
int c;
BPTR tempLock=NULL;
struct DosEnvec *driveEnv;
struct Process *process;
APTR oldWdw;
/*Disable requestors during the execution of this function*/
process=(struct Process *)FindTask(0L);
oldWdw=process->pr_WindowPtr;
process->pr_WindowPtr=(APTR)(-1);
/*Get the DOS device list*/
dosList=LockDosList(LDF_DEVICES|LDF_READ);
/*Go through each entry*/
while(dosList = NextDosEntry(dosList,LDF_DEVICES|LDF_READ))
{
devNode=(struct DeviceNode *)dosList;
/*If the node in the list is a volume*/
if(devNode->dn_Startup > 1000 &&
(devNode->dn_Task || devNode->dn_Handler || devNode->dn_SegList))
{
/*Get the name of the device*/
temp=(char *)BADDR(devNode->dn_Name);
for(c=0;c<temp[0];c++)
name[c]=temp[c+1];
name[c]=':';
name[c+1]=0;
/*Get the information on the device*/
/* driveEnv=(struct DosEnvec *)
BADDR(((struct FileSysStartupMsg *)
BADDR(devNode->dn_Startup))->fssm_Environ);*/
/*If the volume lock is NULL, the 'dev' is assumed to be the*/
/*name of a device holding an unformatted disk, so compare the*/
/*name to the name of the current node*/
if(volumeLock==NULL)
stat=(stricmp(dev,name)==0);
else
{
/*Otherwise, since 'dev' could hold a volume rather than*/
/*device name, get a lock on it and compare it to the lock*/
/*on the device that was given; if they're the same, we've*/
/*found the drive*/
tempLock=Lock(name,ACCESS_READ);
stat=(SameLock(tempLock,volumeLock)==LOCK_SAME);
}
/*If we've found the drive, get the information on it*/
if(stat)
{
struct FileSysStartupMsg *startup;
char *devName;
/*Get a pointer to the structure that holds the needed info*/
startup=(struct FileSysStartupMsg *)BADDR(devNode->dn_Startup);
driveEnv=(struct DosEnvec *)BADDR(startup->fssm_Environ);
/*Get the information*/
layout->unit=startup->fssm_Unit;
devName=(char *)BADDR(startup->fssm_Device);
/*Copy the device name to layout->devName*/
for(c=0;c<devName[0];c++)
layout->devName[c]=devName[c+1];
layout->devName[c+1]=0;
layout->flags=startup->fssm_Flags;
layout->memType=driveEnv->de_BufMemType;
layout->lowCyl=driveEnv->de_LowCyl;
layout->highCyl=driveEnv->de_HighCyl;
layout->surfaces=driveEnv->de_Surfaces;
layout->BPT=driveEnv->de_BlocksPerTrack;
layout->blockSize=driveEnv->de_SizeBlock;
/*Copy the device name back to 'dev'*/
strcpy(dev,name);
/*UnLock the drive lock, if it exists*/
if(tempLock!=NULL)
UnLock(tempLock);
/*Unlock the DOS list*/
UnLockDosList(LDF_DEVICES|LDF_READ);
/*Restore the requester pointer*/
process->pr_WindowPtr=oldWdw;
/*And return TRUE*/
return(TRUE);
}
/*We didn't find the drive, so unlock the lock and try again*/
if(tempLock!=NULL)
UnLock(tempLock);
}
}
/*We didn't find the drive in the list, so unlock the list*/
UnLockDosList(LDF_DEVICES|LDF_READ);
/*Restore the requester pointer*/
process->pr_WindowPtr=oldWdw;
/*And return*/
return(FALSE);
}
/*Create a communications port linking this process to the drive*/
struct IOExtTD *OpenDrive(char *driveDevName,ULONG unit,ULONG flags)
{
struct MsgPort *diskPort;
struct IOExtTD *diskRequest;
/*Create the message port*/
if((diskPort = CreateMsgPort())!=NULL)
{
/*Create the IORequest*/
diskRequest=
(struct IOExtTD *)CreateIORequest(diskPort,sizeof(struct IOExtTD));
if(diskRequest!=NULL)
{
/*Open the device, and return the IORequest if the device*/
/*opened successfully*/
if(!OpenDevice(driveDevName,unit,(struct IORequest *)diskRequest,flags))
return(diskRequest);
/*The device didn't open, so clean up*/
DeleteIORequest(diskRequest);
}
DeleteMsgPort(diskPort);
}
/*Return NULL to indicate that an error occurred*/
return(NULL);
}
/*Close an open device and delete the accompanying port, etc.*/
void CloseDrive(struct IOExtTD *diskRequest)
{
CloseDevice((struct IORequest *)diskRequest);
DeleteMsgPort(diskRequest->iotd_Req.io_Message.mn_ReplyPort);
DeleteIORequest(diskRequest);
}
/*Convert a CSTR to a BSTR*/
BSTR makeBSTR(char *in,char *out)
{
int c;
out[0]=strlen(in);
for(c=0;c<out[0];c++)
out[c+1]=in[c];
return(MKBADDR(out));
}
LONG args[6]=
{
NULL,NULL,0,0,0,0
};
/*Get the command-line arguments given by the user, by using ReadArgs()*/
void parseArgs(char *drive,char *newName,BOOL *ffs,BOOL *icons,BOOL *quick,
BOOL *verify)
{
APTR r;
/*Get the arguments*/
r=ReadArgs("DRIVE/K/A,NAME/K/A,FFS/S,NOICONS/S,QUICK/S,NOVERIFY/S",args,
NULL);
/*If the user didn't specify a drive name, print an error*/
if(args[0]==NULL)
{
printError("You need to specify a drive to format",NULL,NULL);
if(r!=NULL)
FreeArgs(r);
cleanup(200);
}
else
strcpy(drive,(char *)args[0]);
/*Likewise for a name for the newly formatted volume*/
if(args[1]==NULL)
{
printError("You need to specify a name for the volume",NULL,NULL);
cleanup(200);
}
else
strcpy(newName,(char *)args[1]);
/*Get the four togglable settings*/
*ffs=(args[2]!=0);
*icons=(args[3]==0);
*quick=(args[4]!=0);
*verify=(args[5]==0);
/*We're done, so free the ReadArgs result*/
FreeArgs(r);
/*And return*/
return;
}
/*Update the status window (from Workbench), or CLI output (from the CLI)*/
/*If running from the CLI, this also checks to see if the user has pressed*/
/*control-C*/
BOOL updateStatWindow(char *string,UWORD percent)
{
UWORD width;
ULONG class;
UWORD code;
struct TagItem tags[3];
static char Message[80];
struct IntuiMessage *mesg;
/*If this is NULL, we're running from the CLI*/
if(WBenchMsg==NULL)
{
/*Write the string to the CLI, followed by a carriage return (but*/
/*not a line feed)*/
char CR=0x0d;
Write(Output(),string,strlen(string));
Write(Output(),&CR,1);
/*Check to see if the user pressed Control-C*/
if( (SetSignal(0,0) & SIGBREAKF_CTRL_C) == SIGBREAKF_CTRL_C)
{
/*If he did, print "***Break" and return TRUE, to signal that*/
/*the user aborted the formatting process*/
Write(Output(),"\n***Break\n",10);
return(TRUE);
}
/*Otherwise, continue*/
return(FALSE);
}
/*This code is used to update the status window that is displayed when*/
/*the user runs NewFormat from the Workbench*/
/*This puts the message into the text-display gadget*/
/*This copy is so that the caller can change the contents of 'string'*/
/*upon return (which can't be done without the copy, since GadTools*/
/*won't copy the contents of 'string' to an internal buffer*/
strcpy(Message,string);
tags[0].ti_Tag=GTTX_Text;
tags[0].ti_Data=(ULONG)Message;
tags[1].ti_Tag=TAG_DONE;
tags[1].ti_Data=NULL;
GT_SetGadgetAttrsA(StatusGadgets[GD_StatusGadget],
StatusWnd,NULL, tags);
/*Fill the status box with the current percentage of completion*/
SetAPen(StatusWnd->RPort,3);
width=box.left+((box.width-3)*percent)/1000;
RectFill(StatusWnd->RPort,box.left+2,box.top+1,width,box.top+box.height-2);
/*Check user input*/
mesg=GT_GetIMsg(StatusWnd->UserPort);
/*Loop while there are messages*/
while(mesg!=NULL)
{
class=mesg->Class;
code=mesg->Code;
GT_ReplyIMsg(mesg);
switch(class)
{
/*Return TRUE (user abort) if the user pressed 's', 'S'*/
case IDCMP_VANILLAKEY:
if(code=='s' || code=='S')
return(TRUE);
break;
/*Or if the user pressed the 'Stop' gadget*/
case IDCMP_GADGETUP:
return(TRUE);
}
/*Get the next message*/
mesg=GT_GetIMsg(StatusWnd->UserPort);
}
return(FALSE);
}
/*End of Format.c*/